﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TGBTech.Core.Models.Models.BaoCao;
using TGBTech.Core.Models.Models.BaoCao.SoCaiTaiKhoanModel;
using TGB.Core.Infrastructure;
using TGBTech.Core.Models.ChungTu;

namespace TGBTech.Core.Models.Services
{
    public class SoCaiTaiKhoanService
    {
        //const message
        public const String MESSAGE_INVALID_DATE = "Vui lòng kiểm tra ngày tháng đầu vào";
        public const String MESSAGE_INVALID_DATA = "Dữ liệu lỗi tại Data {0}";
        //default value
        public const Decimal DATA_ZERO = 0;
        public SoCaiTaiKhoan createSoCaiTaiKhoan(
            String sohieu, 
            DateTime ngaybatdau, DateTime ngayketthuc, 
            Decimal codauky, Decimal nodauky) 
        {
            //init socaitaikhoan
            SoCaiTaiKhoan socaitaikhoan = new SoCaiTaiKhoan();
            socaitaikhoan.Ngaybatdau = ngaybatdau;
            socaitaikhoan.NgayKetThuc = ngayketthuc;
            socaitaikhoan.SoHieuTK = sohieu;
            socaitaikhoan.ListSoCaiTaiKhoanChiTiet = new List<SoCaiTaiKhoanChiTiet>(); 
            //check valid date
            if (ngaybatdau == null || ngayketthuc == null || ngaybatdau > ngayketthuc)
            {
                socaitaikhoan.Message = MESSAGE_INVALID_DATE;
                return socaitaikhoan;
            }
            //init dbcontext
            using (TGBTechDb dbContext = new TGBTechDb())
            {
                //get taikhoandiengiai
                socaitaikhoan.DienGiaiTK = (from e in dbContext.TaiKhoan where e.MaTaiKhoan == socaitaikhoan.SoHieuTK select e.Name).FirstOrDefault();
                //calculate dauky
                calculateDauKy(ref socaitaikhoan, dbContext.Data, codauky, nodauky);
                //calculate phatsinh
                calculatePhatSinh(ref socaitaikhoan, dbContext.Data);
                //calculate cuoiky
                caculateCuoiKy(ref socaitaikhoan);
            }
            //return socaitaikhoan
            return socaitaikhoan;
        }

        private void caculateCuoiKy(ref SoCaiTaiKhoan socaitaikhoan)
        {
            //init cocuoiky
            socaitaikhoan.CoCuoiKy = DATA_ZERO;
            //calculate nocuoiky
            socaitaikhoan.NoCuoiKy = (socaitaikhoan.NoDauKy + socaitaikhoan.NoPhatSinh) - (socaitaikhoan.CoDauKy + socaitaikhoan.CoPhatSinh);
            //check valid no and calulate co
            if (socaitaikhoan.NoCuoiKy <= DATA_ZERO) 
            {
                socaitaikhoan.CoCuoiKy = -socaitaikhoan.NoCuoiKy;
                socaitaikhoan.NoCuoiKy = DATA_ZERO;  
            }
        }

        private void calculatePhatSinh(ref SoCaiTaiKhoan socaitaikhoan, System.Data.Entity.DbSet<ChungTu.Data> data)
        {
            //init ngaybatdau, ngayketthuc
            var ngaybatdau = socaitaikhoan.Ngaybatdau;
            var ngayketthuc = socaitaikhoan.NgayKetThuc;
            var sohieuTK = socaitaikhoan.SoHieuTK;
            //get data with sohieu
            var queryRes = from e in data
                           where e.TaiKhoanNoId.StartsWith(sohieuTK) || e.TaiKhoanCoId.StartsWith(sohieuTK)
                           select e;
            //get data from ngaybatdau to ngayketthuc
            queryRes = from e in queryRes
                       where e.NgayCT >= ngaybatdau && e.NgayCT <= ngayketthuc
                       select e;
            //calculate nophatsinh
            socaitaikhoan.NoPhatSinh = (from e in queryRes
                                        where e.TaiKhoanNoId.StartsWith(sohieuTK)
                                        select e.SoTien).ToList().Sum();
            //calculate cophatsinh
            socaitaikhoan.CoPhatSinh = (from e in queryRes
                                        where e.TaiKhoanCoId.StartsWith(sohieuTK)
                                        select e.SoTien).ToList().Sum();
            var listRes = queryRes.ToList();
            //init nhatkychung for loop
            SoCaiTaiKhoanChiTiet nhatkychung;
            //loop in listRes
            foreach (var item in listRes)
            {
                //create new nhatkychung
                if (item.TaiKhoanCoId.StartsWith(sohieuTK))
                {
                    nhatkychung = createNhatKyChung(item, true);
                }
                else
                {
                    nhatkychung = createNhatKyChung(item, false);
                }
                //add nhatkychung to list
                socaitaikhoan.ListSoCaiTaiKhoanChiTiet.Add(nhatkychung);
            }
        }

        public static SoCaiTaiKhoanChiTiet createNhatKyChung(Data data, Boolean co)
        {
            //init new NhatKyChung object
            SoCaiTaiKhoanChiTiet nhatkychung = new SoCaiTaiKhoanChiTiet();
            //check valid data
            if (data == null)
            {
                //set error message
                nhatkychung.Message = MESSAGE_INVALID_DATA;
                return nhatkychung;
            }
            //create nhatkychung from data
            nhatkychung.SoHieuCT = data.SoCT;
            nhatkychung.NgayThangCT = data.NgayCT;
            nhatkychung.Co = co;
            //check input co or no
            if (co)
            {
                nhatkychung.SoHieuTaiKhoan = data.TaiKhoanNo.MaTaiKhoan;
                nhatkychung.DienGiaiTaiKhoan = data.DienGiaiNo;
                nhatkychung.SoTienCo = data.SoTien;
            }
            else
            {
                nhatkychung.SoHieuTaiKhoan = data.TaiKhoanCo.MaTaiKhoan;
                nhatkychung.DienGiaiTaiKhoan = data.DienGiaiNo;
                nhatkychung.SoTienNo = data.SoTien;
            }
            //return nhatkychung
            return nhatkychung;
        }

        private void calculateDauKy(ref SoCaiTaiKhoan socaitaikhoan, System.Data.Entity.DbSet<ChungTu.Data> data, decimal codauky, decimal nodauky)
        {
            //init ngaybatdau, sohieuTK
            var ngaybatdau = socaitaikhoan.Ngaybatdau;
            var sohieuTK = socaitaikhoan.SoHieuTK;
            //check codauky exist
            if (codauky > DATA_ZERO)
            {
                //set value to codauky
                socaitaikhoan.CoDauKy = codauky;
                //set zero value to nodauky
                socaitaikhoan.NoDauKy = DATA_ZERO;
            }
            //if codauky not exist
            //check nodauky exist
            else if (nodauky > DATA_ZERO)
            {
                //set value to nodauky
                socaitaikhoan.NoDauKy = nodauky;
                //set default to codauky
                socaitaikhoan.CoDauKy = DATA_ZERO;
            }
            //if nodauky and codauky not exist
            else
            {
                //search data before ngaybatdau
                var queryRes = from e in data
                               where e.NgayCT < ngaybatdau
                               select e;
                //search data with codaukyid equals sohieuTK
                //caculate sum of codauky value
                socaitaikhoan.CoDauKy = (from e in queryRes
                                         where e.TaiKhoanCoId.StartsWith(sohieuTK)
                                         select e.SoTien).ToList().Sum();
                //search data with codaukyid equals sohieuTK
                //caculate sum of codauky value
                socaitaikhoan.NoDauKy = (from e in queryRes
                                         where e.TaiKhoanNoId.StartsWith(sohieuTK)
                                         select e.SoTien).ToList().Sum();
                var value = socaitaikhoan.NoDauKy - socaitaikhoan.CoDauKy;
                if (value > DATA_ZERO)
                {
                    socaitaikhoan.NoDauKy = value;
                    socaitaikhoan.CoDauKy = DATA_ZERO;
                }
                else
                {
                    socaitaikhoan.CoDauKy = -value;
                    socaitaikhoan.NoDauKy = DATA_ZERO;
                }
            }
        }           
    }
}
